package cn.harry.cabinet.server.dto.card

import cn.harry.cabinet.model.entity.Card
import cn.harry.cabinet.repository.CardRepository
import kotlinx.serialization.InternalSerializationApi
import kotlinx.serialization.Serializable
import java.util.Date

/**
 * 卡片响应DTO
 */
@Serializable
@InternalSerializationApi
data class CardResponse(
    val id: Long,
    val cardNumber: String,
    val name: String,
    val type: String,
    val remark: String,
    val status: String,
    val createTime: Long,
    val updateTime: Long
) {
    companion object {
        fun fromCard(card: Card): CardResponse {
            return CardResponse(
                id = card.id,
                cardNumber = card.cardNumber,
                name = card.name,
                type = card.type,
                remark = card.remark,
                status = card.status,
                createTime = card.createTime.time,
                updateTime = card.updateTime.time
            )
        }

        fun fromCardList(cards: List<Card>): List<CardResponse> {
            return cards.map { fromCard(it) }
        }
    }
}

/**
 * 卡片表单请求DTO
 */
@Serializable
@InternalSerializationApi
data class CardFormRequest(
    val cardNumber: String,
    val name: String,
    val type: String,
    val remark: String? = "",  // 允许 null
    val status: String = Card.STATUS_ENABLED
) {
    /**
     * 验证请求数据
     */
    fun isValid(): Boolean {
        return cardNumber.isNotBlank() &&
                name.isNotBlank() &&
                type.isNotBlank() &&
                (status == Card.STATUS_ENABLED || status == Card.STATUS_DISABLED)
    }

    /**
     * 获取验证错误信息
     */
    fun getValidationErrors(): List<String> {
        val errors = mutableListOf<String>()

        if (cardNumber.isBlank()) {
            errors.add("卡号不能为空")
        }

        if (name.isBlank()) {
            errors.add("名称不能为空")
        }

        if (type.isBlank()) {
            errors.add("类型不能为空")
        }

        if (status != Card.STATUS_ENABLED && status != Card.STATUS_DISABLED) {
            errors.add("状态必须是 ENABLED 或 DISABLED")
        }

        return errors
    }

    /**
     * 验证卡号唯一性
     * @param cardRepository 卡片仓库
     * @param excludeId 排除的卡片ID（用于更新时）
     */
    suspend fun validateUniqueCardNumber(
        cardRepository: CardRepository,
        excludeId: Long? = null
    ): String? {
        val existingCard = cardRepository.getByCardNumber(cardNumber)

        // 如果找到了卡片，且不是要排除的ID，则说明卡号重复
        if (existingCard != null && existingCard.id != excludeId) {
            return "卡号 '$cardNumber' 已存在"
        }

        return null
    }

    /**
     * 转换为Card实体
     */
    fun toCard(): Card {
        return Card(
            cardNumber = cardNumber,
            name = name,
            type = type,
            remark = remark ?: "",  // null 时使用空字符串
            status = status,
            createTime = Date(),
            updateTime = Date()
        )
    }
}

/**
 * 卡片搜索请求DTO
 */
@Serializable
@InternalSerializationApi
data class CardSearchRequest(
    val keyword: String = "",
    val type: String? = null,
    val status: String? = null,
    val page: Int = 1,
    val size: Int = 20
)

/**
 * 批量插入卡片请求DTO
 */
@Serializable
@InternalSerializationApi
data class BatchCardRequest(
    val cards: List<CardFormRequest>
) {
    fun isValid(): Boolean {
        return cards.isNotEmpty() && cards.all { it.isValid() }
    }

    fun getValidationErrors(): List<String> {
        val errors = mutableListOf<String>()

        if (cards.isEmpty()) {
            errors.add("卡片列表不能为空")
        }

        cards.forEachIndexed { index, card ->
            val cardErrors = card.getValidationErrors()
            if (cardErrors.isNotEmpty()) {
                errors.add("卡片 ${index + 1}: ${cardErrors.joinToString(", ")}")
            }
        }

        // 检查批量中是否有重复卡号
        val cardNumbers = cards.map { it.cardNumber }
        val duplicates = cardNumbers.groupingBy { it }.eachCount().filter { it.value > 1 }.keys
        if (duplicates.isNotEmpty()) {
            errors.add("批量插入的卡片中存在重复卡号: ${duplicates.joinToString(", ")}")
        }

        return errors
    }
}
